<?php

namespace App\Command\Make;

use Hyperf\Command\Annotation\Command;
use Hyperf\Utils\Str;
use Symfony\Component\Console\Input\InputOption;

#[Command]
class MakeControllerCommand extends GeneratorCommand
{
    public function __construct()
    {
        parent::__construct('make:controller');
        $this->setDescription('Create a new controller class');
    }

    protected function getStub(): string
    {
        return __DIR__ . '/stubs/controller.service.api.stub';
    }

    protected function getDefaultNamespace(): string
    {
        return 'App\\Controller';
    }

    protected function buildClass($name): string
    {
        $controllerNamespace = $this->getNamespace($name);

        $replace = [];


        if ($this->input->getOption('service')) {
            $replace = $this->buildServiceReplacements($replace);
        }

        $replace["use {$controllerNamespace}\AbstractController;\n"] = '';

        return str_replace(
            array_keys($replace), array_values($replace), parent::buildClass($name)
        );
    }

    protected function buildServiceReplacements(array $replace): array
    {
        $serviceClass = $this->parseService($this->input->getOption('service'));

        return array_merge($replace, [
            '{{ namespacedService }}' => $serviceClass,
            '{{namespacedService}}' => $serviceClass,
            '{{ service }}' => class_basename($serviceClass),
            '{{service}}' => class_basename($serviceClass),
            '{{ serviceVariable }}' => lcfirst(class_basename($serviceClass)),
            '{{serviceVariable}}' => lcfirst(class_basename($serviceClass)),
        ]);
    }

    protected function parseService(string $service): string
    {
        if (preg_match('([^A-Za-z0-9_/\\\\])', $service)) {
            throw new \Exception('Service name contains invalid characters.');
        }
        return $this->qualifyService($service);
    }

    /**
     * Qualify the given service class base name.
     */
    protected function qualifyService(string $service): string
    {
        $service = ltrim($service, '\\/');
        $service = str_replace('/', '\\', $service);
        $rootNamespace = $this->rootNamespace();
        if (Str::startsWith($service, $rootNamespace)) {
            return $service;
        }
        return is_dir(BASE_PATH . '/app/Service')
            ? $rootNamespace . 'Service\\' . $service
            : $rootNamespace . $service;
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions(): array
    {
       return array_merge(parent::getOptions(), [
           ['service', 's', InputOption::VALUE_OPTIONAL, 'Generate a controller for the given service.'],
       ]);
    }

}